package thread;

/**
 * 同步块
 * 语法:
 * synchronized(同步监视器对象){
 *     需要同步执行的代码片段
 * }
 *
 * 有效的缩小同步范围可以在保证并发安全的前提下尽可能的提高并发效率
 *
 */
public class SyncDemo2 {
    public static void main(String[] args) {
        Shop shop = new Shop();
        //当两个线程不发生"抢"的时候,buy方法中的同步块应当不生效.这才是合适的锁
//        Shop shop1 = new Shop();
//        Shop shop2 = new Shop();
        Thread t1 = new Thread("王克晶"){
            public void run(){
                shop.buy();
//                shop1.buy();
            }
        };
        Thread t2 = new Thread("范传奇"){
            public void run(){
                shop.buy();
//                shop2.buy();
            }
        };
        t1.start();
        t2.start();
    }
}

class Shop{
    /*
        方法上使用synchronized时,同步监视器对象不可指定.只能是this
     */
//    public synchronized void buy(){
    public void buy(){
        try {
            Thread t = Thread.currentThread();

            System.out.println(t.getName()+":正在挑衣服...");
            Thread.sleep(5000);
            /*
                同步块在使用时要求在"()"中指定同步监视器对象
                该对象的要求:
                1:必须是引用类型
                2:多个需要同步执行该代码块的线程看到的必须是"同一个对象"

                合适的锁对象
                在上述两个要求必须满足的前提下,合适的锁对象还应当具备再多个线程需要
                同步执行该代码块时可以排队执行,不需要排队执行该代码块时可以一起执行.
             */
            synchronized(this){
            //实例化表达式作为锁对象一定失效!多个线程看到的一定不是同一个对象
//            synchronized(new Object()){
             /*
                字符串字面量由于java对其优化,始终看到的是同一个对象,因此多个线程
                在执行该同步块时一定排队执行.但这并非合适的锁对象
             */
//            synchronized ("abc"){
                System.out.println(t.getName()+":正在试衣服...");
                Thread.sleep(5000);
            }

            System.out.println(t.getName()+":结账离开");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}






